/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski, Maciej Gajewski            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
 
 
#ifndef GNETPACKETS_H
#define GNETPACKETS_H


// local
#include "gnettypes.h"



// forward declaration 
class GNetPacket;



// -------------------------- GNetPacketFactory{}  ---------------------------
// ---------------------------------------------------------------------------
typedef GNetPacket * ( *PacketCreator )();
class GNetPacketFactory
{
public:
	// ====================================================
	// singleton
	static GNetPacketFactory * instance();	///< Provides instance pointer

	// ====================================================
	// factory
	
	void registerPacket( const quint64 type, PacketCreator packetCreator )
	{
		_packetCreators.insert( type, packetCreator );
	}
	GNetPacket * createPacket( const GHeader& header )
	{
		if( _packetCreators.contains( header.type() ) )
		{
			return ( *_packetCreators.value( header.type() ) )();
		}
		else
		{
			return 0;
		}
	}

	
private:
	// ====================================================
	// constructor 
	GNetPacketFactory(){}
	static GNetPacketFactory * _pPacketFactoryInstance; ///< Global instance
	
	QMap< quint64, PacketCreator > _packetCreators; ///< Registered packet creators
	
}; // class !GNetPacketFactory
// ---------------------------------------------------------------------------




// --------------------------- GNetPacket{} ----------------------------------
// ---------------------------------------------------------------------------
class GNetPacket : public GPacket
{
	
public:

	/// Packet types
	enum GNetPacketType
	{
		GNETPACKET_FIRST = MKWORD( 'g', 'n', 'e', 't' ), ///< New param value
		
		GNETPACKET_AUTHORIZATION,		///< Autorization information
		GNETPACKET_AUTHORIZATION_ANSWER,
		
		GNETPACKET_UNKNOWN,				///< Unknown packet
		GNETPACKET_LAST
	};

	// construction / destruction
	GNetPacket() : GPacket() {}
	virtual ~GNetPacket() {}

	// type query
	virtual quint64 packetType() const = 0;
    virtual GHeader header() const;

	// packet factory
// 	static GNetPacket * createPacket() = 0;


}; // class !GNetPacket
// ---------------------------------------------------------------------------




// -------------------------- GNetPacketUnknown{} ----------------------------
/// Quasi-packet. Used to read uknown packets from stream.
// ---------------------------------------------------------------------------
class GNetPacketUnknown : public GNetPacket
{
	Q_OBJECT
public:
	GNetPacketUnknown() : GNetPacket() {}
	virtual ~GNetPacketUnknown() {}

	virtual quint64 packetType() const { return GNETPACKET_UNKNOWN; }

	static GNetPacket * createPacket() { return new GNetPacketUnknown(); }

protected:
	virtual void writeData( QDataStream & ) const {}
	virtual void readData( QDataStream & ) {}
	
}; // !GNetPacketUnknown
// ---------------------------------------------------------------------------




// ----------------------- GNetPacketReply{} ---------------------------------
/// Base class for all reply packages. Contains the reqwust id field
/// Which allows to associate it with sepcified request packet
// TODO add error filed to trafer execution status and errro message to client
// ---------------------------------------------------------------------------
class GNetPacketReply : public GNetPacket
{
	Q_OBJECT
public:
	GNetPacketReply( quint32 requestId = -1 )
		: GNetPacket(), _requestId( requestId ) {}
	virtual ~GNetPacketReply() {}
	
	quint32 requestId() const { return _requestId; }

protected:
	quint32 _requestId;
}; // !GNetPacketReply
// ---------------------------------------------------------------------------




// ----------------------- GNetPacketAuthorization{} -------------------------
// ---------------------------------------------------------------------------
class GNetPacketAuthorization : public GNetPacket
{
	Q_OBJECT
			
public:
	GNetPacketAuthorization() : GNetPacket() {}
	virtual ~GNetPacketAuthorization() {}
	
	virtual quint64 packetType() const { return GNETPACKET_AUTHORIZATION; }

	static GNetPacket * createPacket() { return new GNetPacketAuthorization(); }
	
	// ----------------------------------------------------
	// packet specific
	
    void setPassword( const QString & password ) { _password = password; }
    QString password()const { return _password; }
	
	void setLogin( const QString & login ) { _login = login; }
	QString login() const { return _login; }
	
protected:
	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );
private:
    QString _password; ///< password
	QString _login;
	
}; // !GNetPacketAuthorization
// ---------------------------------------------------------------------------




// ---------------------- GNetPacketAuthorizationAnswer{} --------------------
// ---------------------------------------------------------------------------
class GNetPacketAuthorizationAnswer : public GNetPacket
{
	Q_OBJECT
public:

	enum Status
	{
		STATUS_OK,
		STATUS_LOGIN_INCORRECT,
		STATUS_PASSWORD_INCORRECT
	};

	
	// construction / destruction
	GNetPacketAuthorizationAnswer( const Status status = STATUS_OK )
		: GNetPacket(), _status( status ) {}
	virtual ~GNetPacketAuthorizationAnswer() {}
	
	
	virtual quint64 packetType() const { return GNETPACKET_AUTHORIZATION_ANSWER; }

	static GNetPacket * createPacket() { return new GNetPacketAuthorizationAnswer(); }
	
	// packet - specific
	
	
	QString & message() { return _message; }
	void setMessage( const QString & message ) { _message = message; }
	
	Status status() { return _status; }
	void setStatus( const Status status ) { _status = status; }

protected:
	// serialization

	/// Serializes object
	virtual void writeData( QDataStream & out ) const;
	/// Reads object
	virtual void readData( QDataStream & in );

private:
	Status  _status;
	QString _message;
	
}; // !GNetPacketAuthorizationAnswer
// ---------------------------------------------------------------------------



#endif // !GNETPACKETS_H

// eof
